package auth

import (
	"context"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/util/gconv"
	v1 "ruoyi-vue-pro-go/api/auth/v1"
	menuv1 "ruoyi-vue-pro-go/api/menu/v1"
	rolev1 "ruoyi-vue-pro-go/api/role/v1"
	rolemenuv1 "ruoyi-vue-pro-go/api/rolemenu/v1"
	userv1 "ruoyi-vue-pro-go/api/user/v1"
	"ruoyi-vue-pro-go/internal/model/entity"
	vo "ruoyi-vue-pro-go/internal/model/vo"
	"ruoyi-vue-pro-go/internal/service"
	"ruoyi-vue-pro-go/utility/auth"
	"sort"
)

type (
	sAuth struct{}
)

func init() {
	service.RegisterAuth(New())
}

func New() service.IAuth {
	return &sAuth{}
}

func (s *sAuth) Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error) {
	// 检查用户是否存在
	user, err := service.User().GetOneByName(ctx, &userv1.GetOneByNameReq{
		Username: req.Username,
	})
	if err != nil {
		return nil, gerror.New("用户不存在")
	}

	// 2. 验证密码 (假设密码已加密存储)
	if !auth.ComparePassword(user.Password, req.Password) {
		return nil, gerror.New("用户名或密码错误")
	}

	// 3. 生成JWT token
	token, err := auth.GenerateAccessToken(user.Id, user.Username)
	if err != nil {
		return nil, gerror.New("生成token失败")
	}
	refreshToken, err := auth.GenerateRefreshToken(user.Id)
	if err != nil {
		return nil, gerror.New("生成refresh token失败")
	}
	claims, err := auth.ParseToken(token)
	return &v1.LoginRes{
		UserId:       user.Id,
		AccessToken:  token,
		RefreshToken: refreshToken,
		ExpiresTime:  claims.ExpiresAt.String(),
	}, nil
}

func (s *sAuth) Logout(ctx context.Context, req *v1.LogoutReq) (res *v1.LogoutRes, err error) {
	return &v1.LogoutRes{}, nil
}

func (s *sAuth) GetPermissionInfo(ctx context.Context, req *v1.GetPermissionInfoReq) (res *v1.GetPermissionInfoRes, err error) {
	// 从上下文中获取用户ID
	userId := ctx.Value("user_id").(int64)
	//fmt.Println(userId)
	//userId := int64(1)
	// 1.1 获得用户信息
	user, err := service.User().GetOne(ctx, &userv1.GetOneReq{
		Id: userId,
	})
	if err != nil || user == nil {
		return nil, gerror.New("用户不存在")
	}
	// 1.2 获得角色列表
	roleList, err := service.Role().GetListByUserId(ctx, &rolev1.GetListByUserIdReq{
		UserId: user.Id,
	})
	// 1.3 获得菜单列表
	var roleids []int64
	for _, role := range roleList.List {
		roleids = append(roleids, role.Id)
	}
	rolemenuList, err := service.RoleMenu().GetListByRoleIds(ctx, &rolemenuv1.GetListByRoleIdsReq{
		RoleIds: roleids,
	})
	var menuids []int64
	for _, rolemenu := range rolemenuList.List {
		menuids = append(menuids, rolemenu.MenuId)
	}
	menuList, err := service.Menu().GetListByIds(ctx, &menuv1.GetListByIdsReq{
		MenuIds: menuids,
	})
	// 1.4 根据菜单列表获取权限列表
	permissionList := make([]string, 0)
	for _, menu := range menuList.List {
		if menu.Permission != "" {
			permissionList = append(permissionList, menu.Permission)
		}
	}
	var menuListRes []*entity.SystemMenu
	// 过滤掉按钮
	for _, menu := range menuList.List {
		if menu.Type != 3 {
			menuListRes = append(menuListRes, menu)
		}
	}
	var systemUser *vo.SystemUserVO
	err = gconv.Struct(user, &systemUser)
	if err != nil {
		// 处理错误
		return nil, err
	}
	roleCodes := make([]string, 0)
	for _, role := range roleList.List {
		roleCodes = append(roleCodes, role.Code)
	}
	// 构建菜单树
	menuTree := s.buildMenuTree(menuListRes, 0)
	res = &v1.GetPermissionInfoRes{
		List:        menuTree,
		User:        systemUser,
		Roles:       roleCodes,
		Permissions: permissionList,
	}
	return
}

// buildMenuTree 递归构建菜单树
func (s *sAuth) buildMenuTree(menus []*entity.SystemMenu, parentId int64) []*vo.SystemMenuVO {
	var tree []*vo.SystemMenuVO
	var treevo []*vo.SystemMenuVO
	gconv.Struct(menus, &treevo)
	for _, menu := range treevo {
		if menu.ParentId == parentId {
			children := s.buildMenuTree(menus, menu.Id)
			if len(children) > 0 {
				menu.Children = children
			}
			tree = append(tree, menu)
		}
	}

	// 按sort排序
	sort.Slice(tree, func(i, j int) bool {
		return tree[i].Sort < tree[j].Sort
	})

	return tree
}

func (s *sAuth) Refresh(ctx context.Context, req *v1.RefreshReq) (*v1.LoginRes, error) {
	claims, err := auth.ParseToken(req.Token)
	if err != nil {
		return nil, gerror.New("无效的token")
	}

	// 检查用户是否存在
	record, err := service.User().GetOne(ctx, &userv1.GetOneReq{
		Id: claims.UserId,
	})
	if err != nil || record == nil {
		return nil, gerror.New("用户不存在")
	}

	// 生成新token
	newToken, err := auth.GenerateAccessToken(claims.UserId, claims.Username)
	if err != nil {
		return nil, gerror.New("生成token失败")
	}
	refreshToken, err := auth.GenerateRefreshToken(claims.UserId)
	if err != nil {
		return nil, gerror.New("生成refresh token失败")
	}
	return &v1.LoginRes{
		UserId:       claims.UserId,
		AccessToken:  newToken,
		RefreshToken: refreshToken,
		ExpiresTime:  claims.ExpiresAt.String(),
	}, nil
}
